
package com.probiz.estore.core.event;

import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jgroups.Address;
import org.jgroups.ChannelClosedException;
import org.jgroups.ChannelNotConnectedException;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;
import org.jgroups.View;

import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.core.filter.PageCacheFilter;
import com.probiz.estore.core.util.CacheUtil;
import com.probiz.estore.core.util.ContextUtil;
import com.probiz.estore.event.PromoRefreshEvent;
import com.probiz.estore.sales.engine.PRuleManager;
import com.probiz.estore.solrsearch.service.SolrSearchService;
import com.probiz.estore.webapp.event.SolrIndexRefreshEvent;

/**
 * 基于JGroup 组播实现。
 * 高效、实时
 */
public class EventUtil extends ReceiverAdapter {
	private static final Log		logger			= LogFactory
															.getLog(EventUtil.class);
	private String		clusterName	   = "PROBIZ_ESTORE_CLUSTER"; //默认
	private JChannel				channel;
	private final static EventUtil	eventUtil		= new EventUtil();
	//自身地址
	private Address  address;

	public JChannel getChannel() {
		return channel;
	}

	public void start() throws Exception {
		channel = new JChannel();
		channel.setReceiver(this);
		channel.connect(clusterName);
		address= channel.getLocalAddress();
	}

	public static EventUtil getInstance() {
		return eventUtil;
	}

	public void viewAccepted(View new_view) {
		logger.info("#JGroup:  ** view: "+ new_view);
	}

	public void receive(Message msg) {
		if(!msg.getSrc().equals(address)){
			//注意：只处理组播其他成员发送过来的消息，因为自身的event已立即处理。
			logger.info("#JGroup:  Received Message: " + msg.getSrc() + ": " + msg.getObject());
			ApplicationEvent event = (ApplicationEvent) msg.getObject();
			if( (ContextUtil.isFront() && event.is4Front()) || (ContextUtil.isStoreAdmin() && event.is4Admin()) ){
				//注意：只有适用于当前平台的事件才处理
				logger.info("#JGroup:  Accept Message: " + msg.getSrc() + ": " + msg.getObject());
				handle(event);
			}
		}
	}

	public void send(Serializable obj) {
		Message msg = new Message();
		msg.setObject(obj);
		try {
			channel.send(msg);
		} catch (ChannelNotConnectedException e) {
			e.printStackTrace();
		} catch (ChannelClosedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 触发事件
	 * 
	 * @param event
	 */
	public void fire(ApplicationEvent event) {
		logger.info("#JGroup:  Fire application event: " + event);
		if(event.is4Self()){
			//适用于当前平台，自身马上处理event
			handle(event);
		}
		//发送事件
		send(event);
	}

	/**
	 * 处理事件
	 * 
	 * @param event
	 */
	public void handle(ApplicationEvent event) {
		logger.info("#JGroup:  Processing application event: " + event);
		if (event instanceof ConfigChangedEvent) {
			handleConfigChangedEvent((ConfigChangedEvent) event);
		} else if (event instanceof AdminCacheClearEvent) {
			handleAdminCacheClearEvent((AdminCacheClearEvent) event);
		}else if (event instanceof FrontCacheClearEvent) {
			handleFrontCacheClearEvent((FrontCacheClearEvent) event);
		} else if (event instanceof StoreFrontCache4ProductClearEvent) {
			handleFrontCache4ProductClearEvent((StoreFrontCache4ProductClearEvent) event);
		} else if (event instanceof PromoRefreshEvent) {
			handlePromoRefreshEvent((PromoRefreshEvent) event);
		}else if (event instanceof MenuRoleDataCacheClearEvent) {
			handleMenuRoleDataCacheClearEvent((MenuRoleDataCacheClearEvent) event);
		}else if (event instanceof AcegiUserDataCacheClearEvent) {
			handleAcegiUserDataCacheClearEvent((AcegiUserDataCacheClearEvent) event);
		}else if (event instanceof SolrIndexRefreshEvent) {
			handleSolrIndexRefreshEvent((SolrIndexRefreshEvent) event);
		}
		logger.info("#JGroup:  Done processing application event: " + event);
	}



	private void handlePromoRefreshEvent(PromoRefreshEvent event) {
		PRuleManager pruleManager = (PRuleManager) ContextUtil
				.getSpringBeanById("pruleManager");
		pruleManager.refresh();

	}

	private void handleConfigChangedEvent(ConfigChangedEvent event) {
		// 更新系统配置缓存先，对于不存储起来的系统配置，通过下面代码立刻生效；因此系统配置不再需要使用缓存
		ConfigUtil.getInstance().onConfigChanged();

		// 更新CacheFilter的缓存设置(只对前台起作用，前台web.xml已配置PageCacheFilter)
		PageCacheFilter cacheFilter = (PageCacheFilter) ContextUtil
				.getSpringBeanById("cacheFilterBean");
		if (cacheFilter != null) {
			cacheFilter.onConfigChanged(event);
		}
		// 如果还有其他bean/filter不能自动更新的，在下面处理

	}

	private void handleAdminCacheClearEvent(AdminCacheClearEvent event) {
		CacheUtil.getInstance().clearAllServerSideCaches();
	}
	
	private void handleFrontCacheClearEvent(FrontCacheClearEvent event) {
		CacheUtil.getInstance().clearAllServerSideCaches();
	}
	
	private void handleFrontCache4ProductClearEvent(StoreFrontCache4ProductClearEvent event) {
		CacheUtil.getInstance().clearAllPageCacheByProduct(event.getProductId());
	}
	
	private void handleMenuRoleDataCacheClearEvent(MenuRoleDataCacheClearEvent event) {
		CacheUtil.getInstance().clearDataCacheByName(CacheUtil.URL_RESOURCES_CACHE);
		ContextUtil.getInstance().reloadMenuRepository();
	}
	
	private void handleAcegiUserDataCacheClearEvent(AcegiUserDataCacheClearEvent event) {
		CacheUtil.getInstance().clearDataCacheByName(CacheUtil.ACEGI_USER_CACHE);
		
	}
	
	private void handleSolrIndexRefreshEvent(SolrIndexRefreshEvent event) {
		SolrSearchService solrIndexService = (SolrSearchService) ContextUtil.getSpringBeanById("solrIndexService");
		solrIndexService.buildFullIndex();
	}

	public String getClusterName() {
		return clusterName;
	}

	public void setClusterName(String clusterName) {
		this.clusterName = clusterName;
	}
	
	

}
